import dateutil.parser
from dateutil import rrule
import datetime, re, logging
    
def subList(l):
    """
    >>> subList('abcd')
    ['abcd', 'abc', 'bcd', 'ab', 'bc', 'cd', 'a', 'b', 'c', 'd']"""
    
    result = []
    for i in range(len(l)):
        for j in range(len(l), i, -1):
            if j-i < 8:
                if l[i:j]:            
                    result.append(l[i:j])
    result.sort(lambda x,y: len(y) - len(x))
    return result   
    
def phrases(s):
    """
    >>> phrases("one two three")
    ['one two three', 'two three', 'one two', 'three', 'one', 'two']
    """
    phraseLists = subList(s.split())
    result = [" ".join(p) for p in phraseLists]
    result.sort(lambda x,y: len(y) - len(x))
    return result

today = datetime.datetime.today().replace(hour=0,minute=0,second=0,microsecond=0)
    
class CautiousParser(dateutil.parser.parser):
    def cautiousParse(self, timestr, **kwargs):
        res = self._parse(timestr, **kwargs)
        if res and res.month and res.day and (res.year < today.year+3):
            return self.parse(timestr, **kwargs)
        else:
            return None        

cautiousParser = CautiousParser()

spanRe = re.compile(r"(to|thru|through|-|bis)\W*\w+")    
def findDate(s):
    """
    >>> findDate('Linux Picnic Saturday, August 9, 2008 12-6p Dunn Loring Park in Vienna')
    >>> findDate("17-Apr-07 Spring Fundamentals")
    datetime.datetime(2007, 4, 17, 0, 0)
    >>> findDate("Saturday")
    >>> findDate("The amazing Number 7!")
    >>> findDate("February 2 08")
    datetime.datetime(2008, 2, 2, 0, 0)
    >>> findDate("Maybe Feb. 27, 2008 will be cloudy?")
    datetime.datetime(2008, 2, 27, 0, 0)
    """
    for checkThis in phrases(s):
        if (4 < len(checkThis) < 50):
            try:
                result = cautiousParser.cautiousParse(checkThis) or \
                         cautiousParser.cautiousParse(spanRe.sub('', checkThis))
                if result:
                    return result.replace(tzinfo=None)         
            except (ValueError, TypeError, OverflowError), e:        
                pass
    return None

dayAbbrevs = 'sun mon tues wednes thurs fri satur'.split()
weekdays = (rrule.SU, rrule.MO, rrule.TU, rrule.WE, rrule.TH, rrule.FR, rrule.SA)
weekdayReader = dict(zip(dayAbbrevs, weekdays))
whichDayReader = {'1st':1,'first':1,'2nd':2,'second':2,'third':3,'3rd':3,'fourth':4,'4th':4,'last':-1}
monthlyFinder = re.compile('(\w+)\s+(sun|mon|tues|wednes|thurs|fri|satur)day', re.DOTALL | re.IGNORECASE)    
def findPeriodic(s):
    matchobj = monthlyFinder.search(s)
    if matchobj:
        n, wkday = matchobj.groups()
        try:
            n = whichDayReader[n.lower()]
            wkday = weekdayReader[wkday.lower()]
            return list(rrule.rrule(rrule.MONTHLY,count=6,byweekday=wkday(n)))
        except (IndexError, KeyError):
            return None
    return None
        
def _test():
    import doctest
    doctest.testmod()

if __name__ == "__main__":
    _test()